"use strict";
var GeoCom_1 = require('./GeoCom');
var SurveyClass = require('./SurveyClass');
var q = require('q');
var co = require('co');
var BaseController_1 = require('./../BaseController');
var chalk = require('chalk');
/**
 * 控制全站仪的基础控制器,默认半圆观测,不同的测量控制器应继承自该类
 */
class TPSController extends BaseController_1.BaseController {
    /**
     * 初始化控制器,打开com��
     */
    constructor(portName) {
        super();
        /**
         * 控制全站仪的geocom
         */
        this.geoCom = null;
        /**
         * 全站仪的数据管理
         */
        this.tps = null;
        /**
         * 测量方法,默认为半圆测回法
         */
        this._observeMethod = SurveyClass.ObserveMethod.HalfCircle;
        this.geoCom = new GeoCom_1.GeoCom(portName);
        this.comPort = this.geoCom;
        this.tps = new SurveyClass.TPS();
    }
    /**
     * 准备测站数据
     */
    prepareStation(stationCoor, targetList) {
        this.tps = new SurveyClass.TPS(stationCoor.e, stationCoor.n, stationCoor.h);
        for (let item of targetList) {
            this.tps.addPoint(item.name, item);
        }
    }
    /**
     * 设置操作类的测量方法,半测回或全圆
     */
    setObserveMethod(method) {
        this._observeMethod = method;
    }
    _prepareTurnData() {
        var turn = new SurveyClass.SurveyTurn();
        turn.copyPointsFromTPS(this.tps);
        //测量点数超过3个（不包3个）时需要增加归零点
        if (turn.surveyResultList.length > 3) {
            var zeroPoint = Object.assign(new SurveyClass.SurveyPoint(), turn.surveyResultList[0]);
            turn.surveyResultList.push(zeroPoint);
        }
        return turn;
    }
    /**
     * 开始测量,返回一组promise的测回数据
     * 构建一个测回数据,开始测量,将测量结果填入测回数据中,最终返回该测回数据
     */
    survey() {
        //测量前的准备工作
        this.preSurvey && this.preSurvey();
        var tempTurn = this._prepareTurnData(); //准备好本次的测回结果数据
        var _this = this;
        return co(function* () {
            if (_this._working)
                return null;
            _this._working = true;
            yield q.delay(800); //略微延迟一下防止串口未打开
            _this.tps.setFace(0); //盘左
            yield _this._halfRoundSurvey(tempTurn);
            if (_this._observeMethod === SurveyClass.ObserveMethod.FullCircle) {
                _this.tps.setFace(1); //盘右
                yield _this._halfRoundSurvey(tempTurn);
            }
            //重新修正角度
            tempTurn.calibrate(_this._observeMethod);
            for (let pt of tempTurn.surveyResultList) {
                //计算该点本次最终测量的坐标
                pt.pass && _this.tps.caculateCoor(pt);
            }
            _this.tps.setFace(0); //盘左
            _this._working = false;
            return tempTurn;
        });
    }
    /**
     * 半测回测测量
     */
    _halfRoundSurvey(turn) {
        var _this = this;
        return co(function* () {
            var failList = []; //补测列表
            for (let i = 0; i < turn.surveyResultList.length; i++) {
                if (!_this.enabled) return;
                //测量该点
                console.log(chalk.gray('开始测量:') + chalk.blue(turn.surveyResultList[i].name));
                var pass = yield _this._singlePointSurvey(turn.surveyResultList[i]);
                if (!pass) {
                    console.log(chalk.red('失败:') + chalk.gray(turn.surveyResultList[i].name));
                    failList.push(i);
                } else {
                    console.log(chalk.green('成功:') + chalk.gray(turn.surveyResultList[i].name));
                }
            }
            //补测
            for (let key of failList) {
                console.log(chalk.yellow('补测:') + chalk.gray(turn.surveyResultList[key].name));
                pass = yield _this._singlePointSurvey(turn.surveyResultList[key]);
                if (!pass) {
                    console.log(chalk.red('失败') + '   放弃');
                }
            }
        });
    }
    /**
     * 单点测量
     */
    _singlePointSurvey(point) {
        var _this = this;
        return co(function* () {
            if (!_this.enabled) return false;
            var hz = _this.tps.getHz(point);
            var hv = _this.tps.getHv(point);
            //转向测量��
            yield _this.geoCom.makePosition(hz, hv);
            if (!_this.enabled) return false;
            //测量该点
            var result = yield _this.geoCom.measure();
            //如果能观测到数据,并且验证正确
            if (result && _this.tps.checkSurveyPointValidate(point.name, result.hz, result.hv, result.slope)) {
                //赋值到该点的角度和距离
                _this.tps.parseResult(point, result);
                return true;
            }
            else {
                return false;
            }
        });
    }
    /**
    * 学习测量,返回一个TPS学习点StudyPoint
    * @param{point} TPS学习点StudyPoint，学习测量后更新该学习点
    */
    learnSurvey(point) {
        var _this = this;
        return co(function* () {
            yield q.delay(500); //略微延迟一��防止串口未打开
            //默认打开ATR和有棱镜模式
            yield _this.geoCom.toggleATR(1);
            yield _this.geoCom.toggleMeaureMethod('IR');
            //测量该点
            var foreResult = yield _this.geoCom.measure();
            //如果能观测到数据
            var ptCoor = null;
            if (foreResult) {
                //该点测量后天顶距小于PI，为盘左
                if (foreResult.hv < Math.PI) {
                    ptCoor = _this.tps.convertToXYZ(foreResult.hz, foreResult.hv, foreResult.slope);
                    point.e = ptCoor.e;
                    point.n = ptCoor.n;
                    point.h = ptCoor.h;
                    return true;
                }
                else {
                    var hv = 2 * Math.PI - foreResult.hv;
                    var hz = foreResult.hz - Math.PI;
                    if (hz < 0) {
                        hz = hz + 2 * Math.PI;
                    }
                    yield _this.geoCom.makePosition(hz, hv);
                    var result = yield _this.geoCom.measure();
                    if (result) {
                        ptCoor = _this.tps.convertToXYZ(result.hz, result.hv, result.slope);
                        point.e = ptCoor.e;
                        point.n = ptCoor.n;
                        point.h = ptCoor.h;
                        return true;
                    }
                    else {
                        return false;
                    }
                }
            }
            else {
                return false;
            }
        });
    }
}
exports.TPSController = TPSController;
